use gmsg_db::GmsgType;
use honeybee::mongodb;
use honeybee::mongodb::bson;
use honeybee::prelude::*;
use honeybee::Result;

use crate::gmsg_cache::{GmsgCacheActor, QueryGmsgs};

use super::User;

impl User {
    pub async fn login_process_gmsgs(&mut self) -> Result<()> {
        let gmsg_cache_addr = GmsgCacheActor::from_registry().await?;
        let msgs = gmsg_cache_addr.call(QueryGmsgs).await?;
        for msg in msgs {
            if let Err(err) = self
                .handle_gmsg(&msg._id.to_hex(), msg.msg_type, &msg.msg, msg.expire_time)
                .await
            {
                error!(
                    "{} login process gmsg object_id:{} msg_type:{:?} msg:{} expire_time:{} err:{}",
                    self, msg._id, msg.msg_type, msg.msg, msg.expire_time, err
                );
            }
        }
        Ok(())
    }

    async fn handle_gmsg(
        &mut self,
        object_id: &str,
        msg_type: GmsgType,
        msg_doc: &mongodb::bson::Document,
        expire_time: i64,
    ) -> Result<()> {
        if self.gmsg.contains_key(object_id) {
            return Ok(());
        }
        self.gmsg.insert(object_id.into(), expire_time);
        info!(
            "{} handle gmsg object_id:{} msg_type:{:?} msg_doc:{} expire_time:{}",
            self, object_id, msg_type, msg_doc, expire_time
        );
        match msg_type {
            GmsgType::GmsgTest => {
                if let Err(err) = self.handle_gmsg_test(bson::from_document(msg_doc.clone())?) {
                    error!(
                        "{} handle umsg object_id:{} type:{:?} msg:{} err:{}",
                        self, object_id, msg_type, msg_doc, err,
                    );
                }
            }
        }
        Ok(())
    }

    fn handle_gmsg_test(&mut self, msg: gmsg_db::GmsgTest) -> Result<()> {
        info!("{} handle gmsg:{:?} success", self, msg);
        Ok(())
    }
}

#[async_trait::async_trait]
impl Handler<proto::NewGmsgNotify> for User {
    async fn handle(&mut self, _ctx: &mut Context<Self>, msg: proto::NewGmsgNotify) -> Result<()> {
        let msg_doc = bson::Document::from_reader(&mut msg.msg_bytes.as_slice())?;
        if let Err(err) = self
            .handle_gmsg(&msg.object_id, msg.msg_type, &msg_doc, msg.expire_time)
            .await
        {
            error!(
                "{} handle gmsg object_id:{} msg_type:{:?} msg:{} expire_time:{} err:{}",
                self, msg.object_id, msg.msg_type, msg_doc, msg.expire_time, err
            )
        }
        Ok(())
    }
}
